{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from bqplot import (ColorScale, GridHeatMap, Axis, \n",
    "                    Figure, OrdinalScale, LinearScale)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Get Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "np.random.seed(0)\n",
    "data = np.random.randn(10, 10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Basic Heat map"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "col_sc = ColorScale()\n",
    "grid_map = GridHeatMap(color=data, scales={'color': col_sc})\n",
    "\n",
    "Figure(marks=[grid_map], padding_y=0.0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "grid_map.display_format = '.2f'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "grid_map.font_style={'font-size': '12px', 'fill':'black', 'font-weight': 'bold'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "grid_map.display_format = None"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Heat map with axes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_sc, y_sc, col_sc = OrdinalScale(), OrdinalScale(reverse=True), ColorScale()\n",
    "\n",
    "grid_map = GridHeatMap(color=data, scales={'column': x_sc, 'row': y_sc, 'color': col_sc})\n",
    "ax_x, ax_y = Axis(scale=x_sc), Axis(scale=y_sc, orientation='vertical')\n",
    "\n",
    "Figure(marks=[grid_map], axes=[ax_x, ax_y], padding_y=0.0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Non Uniform Heat map"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_sc, y_sc, col_sc = LinearScale(), LinearScale(reverse=True), ColorScale()\n",
    "ax_x = Axis(scale=x_sc)\n",
    "ax_y = Axis(scale=y_sc, orientation='vertical')\n",
    "\n",
    "## The data along the rows is not uniform. Hence the 5th row(from top) of the map\n",
    "## is twice the height of the remaining rows.\n",
    "row_data = np.arange(10)\n",
    "row_data[5:] = np.arange(6, 11)\n",
    "\n",
    "column_data = np.arange(10, 20)\n",
    "\n",
    "grid_map = GridHeatMap(row=row_data, column=column_data, color=data,\n",
    "                       scales={'row': y_sc, 'column': x_sc, 'color': col_sc})\n",
    "Figure(marks=[grid_map], padding_y=0.0, axes=[ax_x, ax_y])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "print(row_data.shape)\n",
    "print(column_data.shape)\n",
    "print(data.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Alignment of the data with respect to the grid"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For a `N-by-N` matrix, `N+1` points along the row or the column are assumed to be end points."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_sc, y_sc, col_sc = LinearScale(), LinearScale(reverse=True), ColorScale()\n",
    "ax_x = Axis(scale=x_sc)\n",
    "ax_y = Axis(scale=y_sc, orientation='vertical')\n",
    "\n",
    "row_data = np.arange(11)\n",
    "column_data = np.arange(10, 21)\n",
    "\n",
    "grid_map = GridHeatMap(row=row_data, column=column_data, color=data,\n",
    "                       scales={'row': y_sc, 'column': x_sc, 'color': col_sc})\n",
    "Figure(marks=[grid_map], padding_y=0.0, axes=[ax_x, ax_y])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "By default, for `N` points along any dimension, data aligns to the `start` of the rectangles in the grid. \n",
    "The grid extends infinitely in the other direction. By default, the grid extends infintely\n",
    "towards the bottom and the right."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_sc, y_sc, col_sc = LinearScale(), LinearScale(reverse=True, max=15), ColorScale()\n",
    "ax_x = Axis(scale=x_sc)\n",
    "ax_y = Axis(scale=y_sc, orientation='vertical')\n",
    "\n",
    "row_data = np.arange(10)\n",
    "column_data = np.arange(10, 20)\n",
    "\n",
    "grid_map = GridHeatMap(row=row_data, column=column_data, color=data,\n",
    "                       scales={'row': y_sc, 'column': x_sc, 'color': col_sc})\n",
    "Figure(marks=[grid_map], padding_y=0.0, axes=[ax_x, ax_y])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "By changing the `row_align` and `column_align` properties, the grid can extend in the opposite direction"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_sc, y_sc, col_sc = LinearScale(), LinearScale(reverse=True, min=-5, max=15), ColorScale()\n",
    "ax_x = Axis(scale=x_sc)\n",
    "ax_y = Axis(scale=y_sc, orientation='vertical')\n",
    "\n",
    "row_data = np.arange(10)\n",
    "column_data = np.arange(10, 20)\n",
    "\n",
    "grid_map = GridHeatMap(row=row_data, column=column_data, color=data,\n",
    "                      scales={'row': y_sc, 'column': x_sc, 'color': col_sc},\n",
    "                      row_align='end')\n",
    "Figure(marks=[grid_map], padding_y=0.0, axes=[ax_x, ax_y])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For `N+1` points on any direction, the grid extends infintely in both directions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_sc, y_sc, col_sc = LinearScale(), LinearScale(reverse=True, min=-5, max=15), ColorScale()\n",
    "ax_x = Axis(scale=x_sc)\n",
    "ax_y = Axis(scale=y_sc, orientation='vertical')\n",
    "\n",
    "row_data = np.arange(9)\n",
    "column_data = np.arange(10, 20)\n",
    "\n",
    "grid_map = GridHeatMap(row=row_data, column=column_data, color=data, \n",
    "                       scales={'row': y_sc, 'column': x_sc, 'color': col_sc}, row_align='end')\n",
    "Figure(marks=[grid_map], padding_y=0.0, axes=[ax_x, ax_y])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Changing opacity and stroke"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "col_sc = ColorScale()\n",
    "\n",
    "grid_map = GridHeatMap(color=data, scales={'color': col_sc}, opacity=0.3, stroke='white')\n",
    "Figure(marks=[grid_map], padding_y=0.0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Selections on the grid map"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Selection on the `GridHeatMap` works similar to excel. Clicking on a cell selects the cell, and deselects the previous selection. Using the `Ctrl` key allows multiple cells to be selected, while the `Shift` key selects the range from the last cell in the selection to the current cell."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = np.random.randn(10, 10)\n",
    "\n",
    "col_sc = ColorScale()\n",
    "grid_map = GridHeatMap(color=data, scales={'color': col_sc}, interactions={'click':'select'},\n",
    "                      selected_style={'opacity': '1.0'}, unselected_style={'opacity': 0.4})\n",
    "\n",
    "Figure(marks=[grid_map], padding_y=0.0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `selected` trait of a `GridHeatMap` contains a list of lists, with each sub-list containing the row and column index of a selected cell."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "grid_map.selected"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Registering `on_element_click` event handler"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from IPython.display import display\n",
    "from bqplot import *\n",
    "\n",
    "np.random.seed(0)\n",
    "data = np.random.randn(10, 10)\n",
    "col_sc = ColorScale()\n",
    "grid_map = GridHeatMap(color=data, scales={'color': col_sc}, \n",
    "                       interactions={'click': 'select'},\n",
    "                       selected_style={'stroke': 'blue', 'stroke-width': 3})\n",
    "figure=Figure(marks=[grid_map], padding_y=0.0)\n",
    "\n",
    "from ipywidgets import Output\n",
    "out = Output()\n",
    "@out.capture()\n",
    "def print_event(self, target):\n",
    "    print(target)\n",
    "    \n",
    "# test\n",
    "print_event(1, 'test output')\n",
    "grid_map.on_element_click(print_event)\n",
    "\n",
    "display(figure)\n",
    "display(out)"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
